package com.ybkj.daijia.api.apirest;

import static com.ybkj.daijia.server.zhuan.Order.ORDER_STATUS_JIEDAN;

import com.ybkj.daijia.ServiceSetting;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.WxSetting;
import com.ybkj.daijia.api.beatpay.utils.BestPayCreateOrder;
import com.ybkj.daijia.api.beatpay.utils.BestPayOrderModel;
import com.ybkj.daijia.api.beatpay.utils.CryptTool;
import com.ybkj.daijia.api.driver.transport.ResultTransport;
import com.ybkj.daijia.api.member.alipay.config.AlipayConfig;
import com.ybkj.daijia.api.member.alipay.sign.MemberOrderSign;
import com.ybkj.daijia.api.member.alipay.sign.RSA;
import com.ybkj.daijia.api.member.alipay.util.AlipayNotify;
import com.ybkj.daijia.api.unionpay.AcpService;
import com.ybkj.daijia.api.unionpay.DemoBase;
import com.ybkj.daijia.api.unionpay.LogUtil;
import com.ybkj.daijia.api.unionpay.SDKConfig;
import com.ybkj.daijia.api.unionpay.SDKConstants;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.api.weixin.WeixinUtil;
import com.ybkj.daijia.api.weixin.tenpayv3.Configuration;
import com.ybkj.daijia.api.weixin.tenpayv3.GetWxOrderno;
import com.ybkj.daijia.api.weixin.tenpayv3.RequestHandler;
import com.ybkj.daijia.api.weixin.tenpayv3.Sha1Util;
import com.ybkj.daijia.api.weixin.tenpayv3.TenpayUtil;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.config.SalesApi;
import com.ybkj.daijia.server.event.model.OrderPassengerHasPayEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhaunOrderArriveEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhuanOrderAcceptEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhuanOrderCancelEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhuanOrderCreateEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhuanOrderRecordEvent;
import com.ybkj.daijia.server.event.model.zhuan.ZhuanOrderRunEvent;
import com.ybkj.daijia.server.mc.Enterprise;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.mc.PassengerAccount;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.DriverRefuseRecord;
import com.ybkj.daijia.server.model.SmsTemplet;
import com.ybkj.daijia.server.model.SmsTemplet.SmsType;
import com.ybkj.daijia.server.model.WxBind;
import com.ybkj.daijia.server.sales.Coupon;
import com.ybkj.daijia.server.sales.CouponRule;
import com.ybkj.daijia.server.sales.CouponRule.CouponType;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.CouponService;
import com.ybkj.daijia.server.service.DriverRefuseRecordService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.ErrandService;
import com.ybkj.daijia.server.service.FreightService;
import com.ybkj.daijia.server.service.MemberService;
import com.ybkj.daijia.server.service.OrderService;
import com.ybkj.daijia.server.service.SmsService;
import com.ybkj.daijia.server.service.WxBindService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.websocket.WebSocketSend;
import com.ybkj.daijia.server.zhuan.Car;
import com.ybkj.daijia.server.zhuan.CarType;
import com.ybkj.daijia.server.zhuan.Order;
import com.ybkj.daijia.server.zhuan.Order.PayTypeDetails;
import com.ybkj.daijia.server.zhuan.OrderStatus;
import com.ybkj.daijia.server.zhuan.OrderTemp;
import com.ybkj.daijia.server.zhuan.PayRecordOrder;
import com.ybkj.daijia.server.zhuan.PayRecordOrder.PayRecordTypeOrder;
import com.ybkj.daijia.serverUtils.HttpClientUtil;
import com.ybkj.daijia.serverUtils.ServiceUtil;
import com.ybkj.daijia.serverUtils.SettingUtils;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller("ApiZhuancheProcessController")
@RequestMapping(value = "api/zhuanche/")
@Slf4j
public class ZhuancheProcessController {

    @Autowired
    private SettingUtils settingUtils;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ZhuancheService zhuancheService;

    @Autowired
    private ErrandService errandService;
    @Autowired
    private FreightService freightService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private DriverService driverService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private WxBindService wxBindService;
    @Autowired
    private DriverRefuseRecordService driverRefuseRecordService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;
    @Autowired
    private SmsService smsService;
    @Autowired
    private SalesApi salesApi;

    // 查询附近服务人员
    @RequestMapping(value = "queryNearDriver", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> queryNearDriver(Double longitude, Double latitude,
        Long carTypeId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            CarType carType = zhuancheService.findCarType(carTypeId);
            if (carType != null) {
                List<Driver> list = driverService.queryNearDrivers(longitude, latitude,
                    Driver.DriverJobType.zhuanche.toString());
                List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
                Setting setting = settingUtils.get();
                for (Driver driver : list) {
                    Long carId = driver.getCarId();
                    if (carId != null) {
                        Car car2 = zhuancheService.findCar(carId);
                        if (car2 != null && carTypeId.equals(car2.getCarTypeId())) {
                            Map<String, Object> m = new HashMap<String, Object>();
                            m.put("driverId", driver.getId());
                            m.put("driverName", driver.getName());
                            m.put("driverUserName", driver.getUsername());
                            m.put("driverHead", setting.getWebUrl() + "/upload/driver/" + driver.getPhoto());
                            m.put("driverStar", driver.getStarLevel());
                            m.put("driverTimes", driver.getDriveTimes());
                            m.put("driverJialing", driver.getjialing());
                            m.put("driverDistance", driver.getDistanceStr());
                            m.put("driverMeter", driver.getDistance() * 1000);
                            if (driver.getStatus().equals(Driver.DRIVER_ONLINE)) {
                                m.put("driverStatus", 0);
                            } else {
                                m.put("driverStatus", 1);
                            }
                            m.put("driverLng", driver.getLongitude());
                            m.put("driverLat", driver.getLatitude());
                            if (null != driver.getCarId()) {
                                if (null != car2) {
                                    m.put("carPhoto", setting.getWebUrl() + "/upload/driverCar/" + car2.getPicture());
                                    m.put("carName", car2.getCarName());
                                }
                            }
                            mapList.add(m);
                        }
                    }
                }
                map.put("data", mapList);
                map.put("success", true);
                map.put("message", "查询附近服务人员成功");
            }
        } catch (Exception e) {
            map.put("success", false);
            map.put("message", "查询附近服务人员失败");
        }
        return map;
    }

    @RequestMapping(value = "getPrice")
    public @ResponseBody
    Map<String, Object> getPrice(Long areaId, Double startLat, Double startLng,
        Double endLat, Double endLng) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Result<Map<String, Long>> result = HttpClientUtil.getDistanceAndTimeValueByTwoPoints(
                startLng, startLat, endLng, endLat);
            Map<String, Long> result2 = result.getResult();
            Long distance = result2.get("distance");// 米
            Long time = result2.get("time");// 秒
            map = zhuancheService.getPrice(areaId, distance, time);
        } catch (Exception e) {
            map.put("success", false);
            map.put("message", "预算失败");
        }
        return map;
    }

    @RequestMapping(value = "getNewPrice")
    public @ResponseBody
    Map<String, Object> getNewPrice(
        @RequestParam(required = true, value = "areaId") Long areaId,
        @RequestParam(required = false, value = "time") Integer time,
        @RequestParam(required = false, value = "mileage") Double mileage) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            map = zhuancheService.getNewPrice(areaId, mileage, Long.valueOf(time));
        } catch (Exception e) {
            map.put("success", false);
            map.put("message", "预算失败");
        }
        return map;
    }

    @RequestMapping(value = "getPriceByCarType")
    public @ResponseBody
    Map<String, Object> getPriceByCarType(Long carTypeId, Double startLat,
        Double startLng, Double endLat, Double endLng) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            CarType cartype = zhuancheService.findCarType(carTypeId);
            if (null != cartype) {
                Result<Map<String, Long>> result = HttpClientUtil.getDistanceAndTimeValueByTwoPoints(
                    startLng, startLat, endLng, endLat);
                Map<String, Long> result2 = result.getResult();
                Long distance = result2.get("distance");// 米
                Long time = result2.get("time");// 秒
                map = zhuancheService.getPrice(cartype.getAreaId(), distance, time);
            } else {
                map.put("success", false);
                map.put("message", "车类型不存在");
            }

        } catch (Exception e) {
            log.error("getPrice error : " + e.getMessage());
        }
        return map;
    }

    @RequestMapping(value = "getCarType")
    public @ResponseBody
    List<Map<String, Object>> getCarType(String ack, Long passengerId,
        Double longitude, Double latitude) {

        Long companyId = null;

        if (StringUtils.isNotBlank(ack)) {
            Company ackCompany = companyService.findByAppKey(ack);
            if (null != ackCompany) {
                companyId = ackCompany.getId();
            }
        }

        if (null == companyId) {
            List<Company> list = companyService.findByAreaCityName(HttpClientUtil.getCityByLngAndLat(
                longitude, latitude));
            Passenger passenger = null;
            if (null != passengerId) {
                passenger = memberService.findOnePassenger(passengerId);
            }
            if (!CollectionUtils.isEmpty(list)) {

                List<Company> notMainCompanys = new ArrayList<Company>();
                Company cityMainCompany = null;

                for (Company c : list) {
                    if (null != passenger) {
                        if (passenger.getCompanyId().equals(c.getId())) {
                            companyId = passenger.getCompanyId();
                            break;
                        } else {
                            if (!c.isCompanyType()) {
                                notMainCompanys.add(c);
                            } else {
                                cityMainCompany = c;
                            }
                        }
                    } else {
                        if (!c.isCompanyType()) {
                            notMainCompanys.add(c);
                        } else {
                            cityMainCompany = c;
                        }
                    }
                }

                if (null == companyId) {
                    if (!CollectionUtils.isEmpty(notMainCompanys)) {
                        companyId = notMainCompanys.get(new Random().nextInt(notMainCompanys.size())).getId();
                    }
                }

                if (null == companyId) {
                    if (null != cityMainCompany) {
                        companyId = cityMainCompany.getId();
                    }
                }

            }
            if (null == companyId) {
                companyId = companyService.getMain().getId();
            }
        }

        List<Map<String, Object>> carTypesMapList = new ArrayList<Map<String, Object>>();
        List<CarType> carTypes = zhuancheService.queryCarTypes(companyId);
        if (!CollectionUtils.isEmpty(carTypes)) {
            for (CarType carType : carTypes) {
                Map<String, Object> carTypesMap = new HashMap<String, Object>();
                carTypesMap.put("carTypeId", carType.getId());
                carTypesMap.put("name", carType.getTypeName());
                carTypesMap.put("areaId", carType.getAreaId());
                carTypesMap.put("picture", carType.getPicture());
                carTypesMap.put("carTypeCompanyId", carType.getCompanyId());
                carTypesMapList.add(carTypesMap);
            }
        }

        return carTypesMapList;
    }

    @RequestMapping(value = "findCarType")
    public @ResponseBody
    Map<String, Object> findCarType(String ack, Long passengerId,
        Long carTypeId, Double longitude, Double latitude) {
        Long companyId = null;
        Map<String, Object> map = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(ack)) {
            Company ackCompany = companyService.findByAppKey(ack);
            if (null != ackCompany) {
                companyId = ackCompany.getId();
            }
        }

        if (null == companyId) {
            List<Company> list = companyService.findByAreaCityName(HttpClientUtil.getCityByLngAndLat(
                longitude, latitude));
            Passenger passenger = null;
            if (null != passengerId) {
                passenger = memberService.findOnePassenger(passengerId);
            }
            if (!CollectionUtils.isEmpty(list)) {

                List<Company> notMainCompanys = new ArrayList<Company>();
                Company cityMainCompany = null;

                for (Company c : list) {
                    if (null != passenger) {
                        if (passenger.getCompanyId().equals(c.getId())) {
                            companyId = passenger.getCompanyId();
                            break;
                        } else {
                            if (!c.isCompanyType()) {
                                notMainCompanys.add(c);
                            } else {
                                cityMainCompany = c;
                            }
                        }
                    } else {
                        if (!c.isCompanyType()) {
                            notMainCompanys.add(c);
                        } else {
                            cityMainCompany = c;
                        }
                    }
                }

                if (null == companyId) {
                    if (!CollectionUtils.isEmpty(notMainCompanys)) {
                        companyId = notMainCompanys.get(new Random().nextInt(notMainCompanys.size())).getId();
                    }
                }

                if (null == companyId) {
                    if (null != cityMainCompany) {
                        companyId = cityMainCompany.getId();
                    }
                }

            }
            if (null == companyId) {
                companyId = companyService.getMain().getId();
            }
        }

        List<CarType> carTypes = zhuancheService.queryCarTypes(companyId);
        if (!CollectionUtils.isEmpty(carTypes)) {
            for (CarType carType : carTypes) {
                if (carType.getId().equals(carTypeId)) {
                    CarType type = zhuancheService.findCarType(carTypeId);
                    map.put("areaId", type.getAreaId());
                }

            }
        }

        return map;
    }

    @RequestMapping(value = "createWeixin", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> createWeixin(String ack, String beginAddress,
        @RequestParam(required = false, value = "beginAddressDetail") String beginAddressDetail,
        Double beginLat, Double beginLng,
        @RequestParam(required = false, value = "endAddress") String endAddress,
        @RequestParam(required = false, value = "endAddressDetail") String endAddressDetail,
        @RequestParam(required = false, value = "endLat") Double endLat,
        @RequestParam(required = false, value = "endLng") Double endLng, String phone, String openId,
        Long carTypeId) {

        log
            .error(
                "recv ack:{},beginAddress:{},beginAddressDetail:{},beginLat:{},beginLng:{},endAddress:{},endAddressDetail:{},endLat:{},endLng:{},phone:{},carTypeId:{}",
                ack, beginAddress, beginAddressDetail, beginLat, beginLng, endAddress,
                endAddressDetail, endLat, endLng, phone, carTypeId);

        Map<String, Object> map = new HashMap<String, Object>();

        if (StringUtils.isBlank(beginAddress) || null == beginLat || null == beginLng
            || StringUtils.isBlank(phone) || null == carTypeId) {
            map.put("success", false);
            map.put("message", "参数错误");
            return map;
        }

        Passenger passenger = memberService.findOnePassengerByPhone(phone);

        if (null == passenger) {
            map.put("success", false);
            map.put("message", "客户不存在，无法下单");
            return map;
        }

        if (passenger.isInBlackList()) {
            map.put("success", false);
            map.put("message", "下单失败");
            return map;
        }

        // 如果存在未支付订单，不能下单
        ServiceSetting serviceSetting = ServiceUtil.checkOpen();
        Long notPayAmounts = 0L;
        notPayAmounts += zhuancheService.countNotPayByPassenger(passenger.getId());
        if (serviceSetting.isPaotui()) {
            notPayAmounts += errandService.countNotPayByPassenger(passenger.getId());
        }
        if (serviceSetting.isDaijia()) {
            notPayAmounts += orderService.countNotPayByPassenger(passenger.getId());
        }
        if (serviceSetting.isFreight()) {
            notPayAmounts += freightService.countNotPayByPassenger(passenger.getId());
        }
        if (notPayAmounts > 0) {
            map.put("success", false);
            map.put("code", ErrorConstantV4.ORDER_NOTPAY_ERROR.getCode());
            map.put("message", ErrorConstantV4.ORDER_NOTPAY_ERROR.getMessage());
            return map;
        }

        // 今天已经下的（新单、销单、执行中）订单不能超过10单
        Long todayAmounts = zhuancheService.countTodayOrderByPassenger(passenger.getId());
        if (todayAmounts >= 10) {
            map.put("success", false);
            map.put("code", ErrorConstantV4.ORDER_RUNNING_ERROR.getCode());
            map.put("message", ErrorConstantV4.ORDER_RUNNING_ERROR.getMessage());
            return map;
        }

        try {
            String channelName = Order.ORDER_TYPE_WEIXIN;
            if (StringUtils.isBlank(openId)) {
                channelName = Order.ORDER_TYPE_WEB;
            }
            Double budgetPay = 0.0;
            Double startPrice = 0.0;
            Double mileagePrice = 0.0;
            Double runTimePrice = 0.0;
            Integer travelTime = 0;
            Double mileage = 0.0;
            CarType cartype = zhuancheService.findCarType(carTypeId);
            Long companyId = cartype.getCompanyId();
            String companyName = cartype.getCompanyName();
            if (beginLat != null && beginLng != null && endLng != null && endLat != null) {
                Result<Map<String, Long>> result = HttpClientUtil.getDistanceAndTimeValueByTwoPoints(
                    beginLng, beginLat, endLng, endLat);
                Map<String, Long> result2 = result.getResult();
                Long distance = result2.get("distance");// 米
                Long time = result2.get("time");// 秒
                Map<String, Object> priceMap = zhuancheService
                    .getPrice(cartype.getAreaId(), distance, time);
                Boolean success = Boolean.valueOf(priceMap.get("success").toString());
                if (success) {
                    budgetPay = Double.valueOf(priceMap.get("money").toString());
                    startPrice = Double.valueOf(priceMap.get("startPrice").toString());
                    mileagePrice = Double.valueOf(priceMap.get("mileagePrice").toString());
                    runTimePrice = Double.valueOf(priceMap.get("travelTimePrice").toString());
                    travelTime = Integer.valueOf(priceMap.get("travelTime").toString());
                    mileage = Double.valueOf(priceMap.get("mileage").toString());
                }
            } else {
                Map<String, Object> priceMap = zhuancheService.getNewPrice(cartype.getAreaId(), 0.0, 0L);
                Boolean success = Boolean.valueOf(priceMap.get("success").toString());
                if (success) {
                    budgetPay = Double.valueOf(priceMap.get("money").toString());
                    startPrice = Double.valueOf(priceMap.get("startPrice").toString());
                    mileagePrice = Double.valueOf(priceMap.get("mileagePrice").toString());
                    runTimePrice = Double.valueOf(priceMap.get("travelTimePrice").toString());
                }
            }

            Result<Order> r = zhuancheService.createOrder(passenger.getId(), passenger.getName(),
                passenger.getPhone(), passenger.getPhone(), companyId, companyName, carTypeId,
                beginAddress, beginAddressDetail, beginLat, beginLng, endAddress, endAddressDetail,
                endLat, endLng, new Date(), budgetPay, startPrice, mileagePrice, runTimePrice,
                travelTime, mileage, null, channelName, null, null);

            if (r.isSuccess()) {

                if (StringUtils.isNotBlank(openId)) {

                    wxBindService.deleteByWxuser(openId);
                    wxBindService.deleteByPhone(phone);

                    WxBind wxBind = new WxBind();
                    wxBind.setCode(null);
                    wxBind.setPhone(phone);
                    wxBind.setStatus(WxBind.WXBIND_STATUS_SUCCESS);
                    wxBind.setWxuser(openId);
                    wxBindService.insertRecrod(wxBind);
                }

                Long orderId = r.getResult().getId();
                Order order = zhuancheService.findOne(orderId);

                ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
                applicationEventMulticaster.multicastEvent(createEvent);

                ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
                applicationEventMulticaster.multicastEvent(orderRecordEvent);

                map.put("success", true);
                map.put("orderId", r.getResult().getId());
                map.put("message", "下单成功!");
                return map;
            } else {
                map.put("success", false);
                map.put("message", r.getMessage());
                return map;
            }

        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", e.getMessage());
            return map;
        }

    }

    // 专车订单销单
    @RequestMapping(value = "cancel", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> cancel(Long orderId, String cause) {
        Map<String, Object> map = new HashMap<String, Object>();
        Order order = zhuancheService.findOne(orderId);
        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            map.put("code", ErrorConstantV4.ORDER_NOT_EXISTS_ERROR.getCode());
            return map;
        } else {
            if (!order.getStatus().equals(Order.ORDER_STATUS_NEW)
                && !order.getStatus().equals(Order.ORDER_STATUS_PAIDAN)
                && !order.getStatus().equals(ORDER_STATUS_JIEDAN)) {
                map.put("success", false);
                if (order.getStatus().equals(Order.ORDER_STATUS_ARRIVE)) {
                    map.put("message", "服务人员已到达预约地,不能销单");
                }
                if (order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                    map.put("message", "订单执行中,不能销单");
                }
                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    map.put("message", "订单已完成,不能销单");
                }
                if (order.getStatus().equals(Order.ORDER_STATUS_XIAODAN)) {
                    map.put("message", "订单已销单,不能销单");
                }
                map.put("code", ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return map;
            }
            try {
                Result<Order> result = zhuancheService.cancelOrder(order, cause, order.getPassengerName(),
                    "customerCancel");
                if (result.isSuccess()) {
                    map.put("success", true);
                    map.put("message", "销单成功");
                    map.put("code", ErrorConstantV4.SUCCESS.getCode());
                    return map;
                } else {
                    map.put("success", false);
                    map.put("message", result.getMessage());
                    map.put("code", ErrorConstantV4.SERVER_ERROR.getCode());
                    return map;
                }
            } catch (Exception e) {
                map.put("success", false);
                map.put("message", "销单失败");
                map.put("code", ErrorConstantV4.SERVER_ERROR.getCode());
                return map;
            }
        }
    }

    // 查询单个专车订单
    @RequestMapping(value = "findOne", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> findOne(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();

        Order order = zhuancheService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        Setting setting = settingUtils.get();

        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");

        Map<String, Object> orderMap = new HashMap<String, Object>();
        orderMap.put("id", order.getId());
        orderMap.put("startAddress", order.getStartAddress());
        orderMap.put("passengerName", order.getPassengerName());
        orderMap.put("passengerPhone", order.getPassengerPhone());
        orderMap.put("passengerId", order.getPassengerId());
        orderMap.put("startLng", order.getStartLng());
        orderMap.put("startLat", order.getStartLat());
        orderMap.put("endAddress", order.getEndAddress());
        orderMap.put("endLng", order.getEndLng());
        orderMap.put("endLat", order.getEndLat());
        orderMap.put("serverTime", format.format(order.getServerTime()));
        orderMap.put("companyId", order.getCompanyId());
        orderMap.put("status", order.getStatus());
        orderMap.put("treatment", order.isTreatment());
        orderMap.put("carTypeName", order.getCarTypeName());
        orderMap.put("review", order.getReview());
        orderMap.put("ifTaxi", order.getIfTaxi());
        if (null != order.getCarId()) {
            Car car = zhuancheService.findCar(order.getCarId());
            if (null != car) {
                orderMap.put("carNumber", car.getCarNumber());
                orderMap.put("carName", car.getCarName());
                orderMap.put("carBodyColor", car.getBodyColor());
            }
        }

        orderMap.put("employId", order.getEmployId());
        if (null != order.getEmployId()) {
            Driver driver = driverService.findOne(order.getEmployId());
            if (null != driver) {
                orderMap.put("employName", driver.getName());
                orderMap.put("starLevel", driver.getStarLevel());
                orderMap.put("driverTimes", driver.getDriveTimes());
                orderMap.put("employUserName", driver.getUsername());
                orderMap.put("employPhone", driver.getPhone());
                if (order.getStatus().equals(ORDER_STATUS_JIEDAN)) {
                    orderMap.put("employLatitude", driver.getLatitude());
                    orderMap.put("employLongitude", driver.getLongitude());
                }
                if (StringUtils.isNotBlank(driver.getPhoto())) {
                    orderMap.put("employPhoto", setting.getWebUrl() + "/upload/driver/" + driver.getPhoto());
                } else {
                    orderMap.put("employPhoto", null);
                }
                orderMap.put("employScore", driver.getStarLevel());
            }
        }

        if (order.getStatus().equals(ORDER_STATUS_JIEDAN)
            || order.getStatus().equals(Order.ORDER_STATUS_ARRIVE)
            || order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)
            || order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)
            || order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            List<OrderStatus> orderStatuss = order.getStatusList();
            if (!CollectionUtils.isEmpty(orderStatuss)) {
                Collections.sort(orderStatuss, new Comparator<OrderStatus>() {
                    public int compare(OrderStatus arg0, OrderStatus arg1) {
                        return arg1.getId().compareTo(arg0.getId());
                    }
                });
                List<OrderStatus> nowOrderStatuss = new ArrayList<OrderStatus>();
                for (OrderStatus orderStatus : orderStatuss) {
                    if (orderStatus.getStatus().equals(ORDER_STATUS_JIEDAN)) {
                        nowOrderStatuss.add(orderStatus);
                        break;
                    } else {
                        nowOrderStatuss.add(orderStatus);
                    }
                }
                if (!CollectionUtils.isEmpty(nowOrderStatuss)) {
                    for (OrderStatus orderStatus : nowOrderStatuss) {
                        if (orderStatus.getStatus().equals(ORDER_STATUS_JIEDAN)) {
                            orderMap.put("acceptTime", format.format(orderStatus.getCreated()));
                        } else if (orderStatus.getStatus().equals(Order.ORDER_STATUS_ARRIVE)) {
                            orderMap.put("arriveTime", format.format(orderStatus.getCreated()));
                        } else if (orderStatus.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
                            orderMap.put("startdriveTime", format.format(orderStatus.getCreated()));
                        } else if (orderStatus.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
                            orderMap.put("arriveDistinationTime", format.format(orderStatus.getCreated()));
                        } else if (orderStatus.getStatus().equals(Order.ORDER_STATUS_OK)) {
                            orderMap.put("finishTime", format.format(orderStatus.getCreated()));
                        }

                    }
                }
            }
        }

        map.put("success", true);
        map.put("data", orderMap);
        return map;
    }

    @RequestMapping(value = "getDriverPlace")
    public @ResponseBody
    Map<String, Object> getDriverPlace(Long driverId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            if (driverId != null && driverId != 0) {
                Driver driver = driverService.findOne(driverId);
                if (driver != null) {
                    map.put("success", true);
                    map.put("longitude", driver.getLongitude());
                    map.put("latitude", driver.getLatitude());
                    map.put("phone", driver.getPhone());
                    try {
                        map.put("place",
                            HttpClientUtil.getPlaceByLngAndLat(driver.getLongitude(), driver.getLatitude()));
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }
                } else {
                    map.put("success", false);
                    map.put("message", "服务人员不存在");
                }
            } else {
                map.put("success", false);
                map.put("message", "服务人员Id不能为空");
            }
        } catch (Exception e) {
            log.error("getDriverPlace error : " + e.getMessage());
            map.put("success", false);
            map.put("message", "查询服务人员位置信息失败");
        }
        return map;
    }

    @RequestMapping(value = "getEmployStatus")
    public @ResponseBody
    Map<String, Object> getEmployStatus(Long driverId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", false);
        if (null != driverId) {
            Driver driver = driverService.findOne(driverId);
            if (null != driver) {
                map.put("status", driver.getStatus());
                if (null != driver.getJobStatus()) {
                    map.put("jobStatus", driver.getJobStatus());
                } else {
                    map.put("jobStatus", -1);
                }
                map.put("success", true);
            }
        }
        return map;
    }

    /**
     * 设置为空闲状态
     *
     * @param orderId
     * @return
     */
    @RequestMapping(value = "updateDriver")
    public @ResponseBody
    Map<String, Object> updateDriver(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", false);
        Order order = zhuancheService.findOne(orderId);

        if (order != null && order.getEmployId() != null) {
            Driver driver = driverService.findOne(order.getEmployId());
            if (null != driver) {
                if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                    driverService.updateStatusAndJobStatus(Driver.DRIVER_ONLINE, null, driver.getId());
                }
                map.put("success", true);
            }
        }
        return map;
    }

    /**
     * 修改服务人员为忙碌状态
     *
     * @param driverId
     * @return
     */
    @RequestMapping(value = "updateBusyDriver")
    public @ResponseBody
    Map<String, Object> updateBusyDriver(Long driverId) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", false);
        Driver driver = driverService.findOne(driverId);
        if (null != driver) {
            if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                driverService.updateStatusAndJobStatus(Driver.DRIVER_BUSY,
                    Driver.DRIVER_JOBSTATUS_ZHUANCHE, driver.getId());
            }
            map.put("success", true);
        }
        return map;
    }

    // 显示催单记录
    @RequestMapping(value = "hurryOrder")
    public @ResponseBody
    Map<String, Object> hurryOrder(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Company orderCompany = null;
            Order order = zhuancheService.findOne(orderId);
            if (null != order) {
                orderCompany = companyService.findOne(order.getCompanyId());
                if (null != orderCompany) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("passengerName", order.getPassengerName());
                    jsonObject.put("passengerPhone", order.getPassengerPhone());
                    jsonObject.put("orderId", order.getId());
                    jsonObject.put("id", order.getId());
                    jsonObject.put("orderNo", order.getOrderNo());
                    jsonObject.put("status", order.getStatus());
                    jsonObject.put("startAddress", order.getStartAddress());
                    jsonObject.put("startLat", order.getStartLat());
                    jsonObject.put("startLng", order.getStartLng());
                    jsonObject.put("type", "hurryZhuancheOrder_company");
                    Company mainCompany = companyService.getMain();
                    WebSocketSend.boardcastToCompany(jsonObject, orderCompany.getId(), mainCompany.getId());
                    map.put("success", true);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    // 支付宝支付前的接口
    @RequestMapping(value = "alipay/prepay")
    public @ResponseBody
    Map<String, Object> alipayPrepay(HttpServletResponse response,
        HttpServletRequest request, Long orderId) {

        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            OrderTemp temp = zhuancheService.findOneTemp(orderId);

            Coupon coupon = null;
            BigDecimal coupon_hasPayed = BigDecimal.ZERO;
            Double discount = null;
            if (null != temp.getCouponId()) {
                coupon = couponService.findOne(temp.getCouponId());
                if (null != coupon) {
                    if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                        coupon_hasPayed = coupon.getCouponRule().getMoney();
                    } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                        discount = coupon.getCouponRule().getDiscount();
                        coupon_hasPayed = (temp.getBudgetPay().multiply(new BigDecimal(1 - (discount / 10))))
                            .setScale(0, BigDecimal.ROUND_DOWN);
                    }
                }
            }

            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "zhuanche_prepay_" + orderId);// 临时表订单Id
            map.put("productName", "专车支付");
            map.put("productDescription", "专车预先支付充值");
            map.put("amount", temp.getBudgetPay().subtract(coupon_hasPayed));
            map.put("notifyURL", setting.getWebUrl() + "/api/zhuanche/alipay/notify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(), "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";
            mapData.put("success", true);
            mapData.put("url", url);
        } catch (Exception e) {
            log.error("api zhuanche prepay 专车支付 error: {}", e);
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 支付宝支付后的接口
    @RequestMapping(value = "alipay/notify")
    public synchronized @ResponseBody
    String alipayNotify(HttpServletResponse response,
        HttpServletRequest request) throws UnsupportedEncodingException {
        Setting setting = settingUtils.get();
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),
            "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),
            "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        log.error("商户订单号：" + out_trade_no);
        log.error("交易号：" + trade_no + "交易状态：" + trade_status);
        if (AlipayNotify.verify(params, setting)) {// 验证成功
            if (trade_status.equals("TRADE_FINISHED")) {
                // 调用专车系统支付成功,把临时表的订单信息新增到真实表中
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                OrderTemp temp = zhuancheService.findOneTemp(orderId);
                if (temp.isTreatment()) {
                    return "success";
                }

                Coupon coupon = null;
                if (null != temp.getCouponId()) {
                    coupon = couponService.findOne(temp.getCouponId());
                }

                PayTypeDetails payType = PayTypeDetails.alipay;
                if (null != coupon) {
                    payType = Order.PayTypeDetails.coupon_alipay;
                }

                Order order = zhuancheService.tempToForever(orderId, payType, coupon);

                if (null != order) {
                    // 客户消费记录
                    Passenger passenger = memberService.findOnePassenger(order.getPassengerId());

                    String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                        + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "元。";

                    if (null != coupon) {
                        if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                        } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                        }
                    }

                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                            PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_ALIPAY,
                            order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                            false, false);
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                        if (null != enterprise) {
                            memberService.moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                                PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                false, false);
                        }
                    }

                    ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
                    applicationEventMulticaster.multicastEvent(createEvent);

                    ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
                    applicationEventMulticaster.multicastEvent(orderRecordEvent);

                    return "success";
                } else {
                    return "fail";
                }

            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 调用专车系统支付成功,把临时表的订单信息新增到真实表中
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                OrderTemp temp = zhuancheService.findOneTemp(orderId);
                if (temp.isTreatment()) {
                    return "success";
                }

                Coupon coupon = null;
                if (null != temp.getCouponId()) {
                    coupon = couponService.findOne(temp.getCouponId());
                }

                PayTypeDetails payType = PayTypeDetails.alipay;
                if (null != coupon) {
                    payType = Order.PayTypeDetails.coupon_alipay;
                }

                Order order = zhuancheService.tempToForever(orderId, payType, coupon);

                if (null != order) {

                    // 客户消费记录
                    Passenger passenger = memberService.findOnePassenger(order.getPassengerId());

                    String payMemo = "订单【" + order.getOrderNo() + "】预付费使用支付宝支付"
                        + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "元。";

                    if (null != coupon) {
                        if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                        } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                            payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                        }
                    }

                    if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                        memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                            PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_ALIPAY,
                            order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                            false, false);
                    } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                        Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                        if (null != enterprise) {
                            memberService.moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                                PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_ALIPAY,
                                order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                                false, false);
                        }
                    }

                    ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
                    applicationEventMulticaster.multicastEvent(createEvent);

                    ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
                    applicationEventMulticaster.multicastEvent(orderRecordEvent);

                    return "success";
                } else {
                    return "fail";
                }
            }
            return "fail";
        } else {
            return "fail";
        }
    }

    @RequestMapping(value = "wx/prepay")
    public synchronized @ResponseBody
    SortedMap<String, String> genpackage(
        HttpServletResponse response, HttpServletRequest request, Long orderId) {

        OrderTemp temp = zhuancheService.findOneTemp(orderId);

        Coupon coupon = null;
        BigDecimal coupon_hasPayed = BigDecimal.ZERO;
        Double discount = null;
        if (null != temp.getCouponId()) {
            coupon = couponService.findOne(temp.getCouponId());
            if (null != coupon) {
                if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                    coupon_hasPayed = coupon.getCouponRule().getMoney();
                } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                    discount = coupon.getCouponRule().getDiscount();
                    coupon_hasPayed = (temp.getBudgetPay().multiply(new BigDecimal(1 - (discount / 10))))
                        .setScale(0, BigDecimal.ROUND_DOWN);
                }
            }
        }

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "下单付费";
        // 商户订单号
        String out_trade_no = "zhuanche_prepay_" + orderId;
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(temp.getBudgetPay().subtract(coupon_hasPayed)
            .multiply(new BigDecimal(100)).intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/zhuanche/wx/notify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
            + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>"
            + trade_type + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                log.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);

        finalpackage.put("success", Boolean.TRUE.toString());

        return finalpackage;

    }

    // 微信支付后接口
    @RequestMapping(value = "wx/notify")
    public synchronized @ResponseBody
    String wxNotify(HttpServletResponse response,
        HttpServletRequest request) throws Exception {

        String out_trade_no = "";

        try {

            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();

            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                }
            }

            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }

            Long orderId = Long.valueOf(out_trade_no.split("_")[2]);

            OrderTemp temp = zhuancheService.findOneTemp(orderId);

            if (temp.isTreatment()) {
                return "SUCCESS";
            }

            Coupon coupon = null;
            if (null != temp.getCouponId()) {
                coupon = couponService.findOne(temp.getCouponId());
            }

            PayTypeDetails payType = PayTypeDetails.alipay;
            if (null != coupon) {
                payType = Order.PayTypeDetails.coupon_alipay;
            }

            Order order = zhuancheService.tempToForever(orderId, payType, coupon);

            if (null != order) {

                // 客户消费记录
                Passenger passenger = memberService.findOnePassenger(order.getPassengerId());

                String payMemo = "订单【" + order.getOrderNo() + "】预付费使用微信支付"
                    + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "元。";

                if (null != coupon) {
                    if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                        payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                    } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                        payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                    }
                }

                if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                    memberService.money(passenger, null, temp.getBudgetPay().negate(), payMemo,
                        PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_WEIXIN,
                        order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null, false,
                        false);
                } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                    Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                    if (null != enterprise) {
                        memberService.moneyEnterprise(enterprise, temp.getBudgetPay().negate(), payMemo,
                            PassengerAccount.OPERATING_SYS, PassengerAccount.PayType.PAYTYPE_WEIXIN,
                            order.getId(), order.getOrderNo(), PassengerAccount.ORDER_TYPE_ZHUANCHE, null,
                            false, false);
                    }
                }

                ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
                applicationEventMulticaster.multicastEvent(createEvent);

                ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
                applicationEventMulticaster.multicastEvent(orderRecordEvent);

                return "SUCCESS";
            } else {
                return "FAIL";
            }

        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }

    }

    // 余额签单支付
    @RequestMapping(value = "balancesignPay", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> balancesignPay(Long orderId, Long passengerId,
        String payType) {

        Map<String, Object> map = new HashMap<String, Object>();

        if (!"balance".equals(payType) && !"sign".equals(payType)) {
            map.put("success", false);
            map.put("message", "支付方式不正确");
            return map;
        }

        OrderTemp temp = zhuancheService.findOneTemp(orderId);
        if (null == temp) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (temp.isTreatment()) {
            map.put("success", false);
            map.put("message", "订单已付费");
            return map;
        }

        Passenger passenger = memberService.findOnePassenger(passengerId);
        if (null == passenger) {
            map.put("success", false);
            map.put("message", "当前客户不存在");
            return map;
        }

        if ("sign".equals(payType)) {
            if (!passenger.isAllowOverdraw()) {
                map.put("success", false);
                map.put("message", "当前客户不能签单");
                return map;
            }
        } else if ("balance".equals(payType)) {
            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                if (passenger.getDrawMoney().add(passenger.getNodrawMoney()).doubleValue() < temp
                    .getBudgetPay().doubleValue()) {
                    map.put("success", false);
                    map.put("message", "当前客户余额不足");
                    return map;
                }
            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                if (enterprise.getDrawMoney().add(enterprise.getNodrawMoney()).doubleValue() < temp
                    .getBudgetPay().doubleValue()) {
                    map.put("success", false);
                    map.put("message", "当前客户余额不足");
                    return map;
                }
            }
        }

        PayTypeDetails prePayType = null;

        Coupon coupon = null;
        if (null != temp.getCouponId()) {
            coupon = couponService.findOne(temp.getCouponId());
        }

        if (null != coupon) {
            if ("sign".equals(payType)) {
                prePayType = Order.PayTypeDetails.coupon_sign;
            } else if ("balance".equals(payType)) {
                prePayType = Order.PayTypeDetails.coupon_balance;
            }
        } else {
            if ("sign".equals(payType)) {
                prePayType = Order.PayTypeDetails.sign;
            } else if ("balance".equals(payType)) {
                prePayType = Order.PayTypeDetails.balance;
            }
        }

        Order order = zhuancheService.tempToForever(orderId, prePayType, coupon);

        if (null != order) {

            // 客户减钱，客户消费记录
            PassengerAccount.PayType ptype = null;

            String payMemo = "";

            if ("sign".equals(payType)) {
                ptype = PassengerAccount.PayType.PAYTYPE_SIGN;
                payMemo += "订单【" + order.getOrderNo() + "】预付费使用签单支付"
                    + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "元。";
            } else if ("balance".equals(payType)) {
                ptype = PassengerAccount.PayType.PAYTYPE_BALANCE;
                payMemo += "订单【" + order.getOrderNo() + "】预付费使用余额支付"
                    + temp.getBudgetPay().setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "元。";
            }

            BigDecimal coupon_mony = BigDecimal.ZERO;
            if (null != coupon) {
                if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
                    payMemo += "并且使用了" + coupon.getCouponRule().getMoney() + "元优惠券。";
                } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                    payMemo += "并且使用了" + coupon.getCouponRule().getDiscount() + "折优惠券。";
                }

                Integer couponType = coupon.getCouponRule().getType();
                if (couponType.equals(CouponRule.TYPE_DEDUCTION)) {
                    coupon_mony = coupon.getCouponRule().getMoney();
                } else if (couponType.equals(CouponRule.TYPE_DISCOUNT)) {
                    Double discount = coupon.getCouponRule().getDiscount();
                    coupon_mony = (temp.getBudgetPay().multiply(new BigDecimal(1 - (discount / 10))))
                        .setScale(0, BigDecimal.ROUND_DOWN);
                }
            }

            if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                memberService.money(passenger, null, (temp.getBudgetPay().subtract(coupon_mony)).negate(),
                    payMemo, PassengerAccount.OPERATING_SYS, ptype, order.getId(), order.getOrderNo(),
                    PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
            } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                if (null != enterprise) {
                    memberService.moneyEnterprise(enterprise,
                        (temp.getBudgetPay().subtract(coupon_mony)).negate(), payMemo,
                        PassengerAccount.OPERATING_SYS, ptype, order.getId(), order.getOrderNo(),
                        PassengerAccount.ORDER_TYPE_ZHUANCHE, null, true, true);
                }
            }

            ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
            applicationEventMulticaster.multicastEvent(createEvent);

            ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
            applicationEventMulticaster.multicastEvent(orderRecordEvent);

            map.put("success", true);
            return map;
        } else {
            map.put("message", "下单失败");
            map.put("success", false);
            return map;
        }

    }

    @RequestMapping(value = "listValidCouponsByPassenger", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> listValidCouponsByPassenger(Long passengerId) {

        Map<String, Object> map = new HashMap<String, Object>();

        List<Map<String, Object>> couponMapList = new ArrayList<Map<String, Object>>();

        List<Coupon> coupons = couponService.listByPassenger(passengerId, CouponType.zhuanche, null, null);
        if (!CollectionUtils.isEmpty(coupons)) {
            for (Coupon coupon : coupons) {
                CouponRule rule = coupon.getCouponRule();
                Map<String, Object> couponMap = new HashMap<String, Object>();
                couponMap.put("couponId", coupon.getId());
                couponMap.put("couponType", rule.getType());
                couponMap.put("couponMoney", rule.getMoney());
                couponMap.put("couponDiscount", rule.getDiscount());
                couponMap.put("couponCode", coupon.getCode());
                couponMap.put("couponTitle", rule.getTitle());
                couponMap.put("startTime", rule.getStart().getTime());
                if (null != rule.getEnd()) {
                    couponMap.put("endTime", rule.getEnd().getTime());
                } else {
                    couponMap.put("endTime", null);
                }
                couponMapList.add(couponMap);
            }
        }
        map.put("code", 0);
        map.put("data", couponMapList);
        map.put("msg", "成功");
        return map;
    }

    @RequestMapping(value = "completeTaskData", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> completeTask(Long orderId) {

        log.error("recv orderId:{}", orderId);

        Map<String, Object> map = new HashMap<String, Object>();

        Order order = zhuancheService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
            map.put("success", false);
            map.put("message", "订单状态不正确");
            return map;
        }

        Driver driver = driverService.findOne(order.getEmployId());
        if (null == driver) {
            map.put("success", false);
            map.put("message", "订单服务人员不存在");
            return map;
        }

        Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
        if (null == passenger) {
            map.put("success", false);
            map.put("message", "订单客户不存在");
            return map;
        }

        try {
            map.put("orderId", order.getId());
            map.put("orderNumber", order.getOrderNo());
            map.put("orderType", "zhuanche");

            map.put("passengerPhone", passenger.getPhone());
            map.put("passengerName", passenger.getName());
            map.put("passengerType", passenger.getTypeStr());

            // 等级
            map.put("passengerGrade", passenger.getGrade_name());

            Company orderCompany = companyService.findOne(order.getCompanyId());
            map.put("orderCompanyName", orderCompany.getAbbreviation());

            Company passengerCompany = companyService.findOne(passenger.getCompanyId());
            map.put("passengerCompanyName", passengerCompany.getAbbreviation());

            if (passenger.getType() == Passenger.TYPE_PASSENGER) {
                map.put("overdraw", passenger.isAllowOverdraw());
                map.put(
                    "virtual",
                    passenger.getDrawMoney().add(passenger.getNodrawMoney())
                        .setScale(2, BigDecimal.ROUND_HALF_UP));
            } else if (passenger.getType() == Passenger.TYPE_ENTERPRISE) {
                Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                map.put("overdraw", enterprise.isAllowOverdraw());
                map.put(
                    "virtual",
                    enterprise.getDrawMoney().add(enterprise.getNodrawMoney())
                        .setScale(2, BigDecimal.ROUND_HALF_UP));
            }

            // 优惠券
            if (null != order.getCouponId()) {
                Coupon coupon = couponService.findOne(order.getCouponId());
                if (null != coupon) {
                    CouponRule couponRule = coupon.getCouponRule();
                    if (couponRule.getType().equals(CouponRule.TYPE_DEDUCTION)) {
                        map.put("couponMoney", couponRule.getMoney());
                    } else if (couponRule.getType().equals(CouponRule.TYPE_DISCOUNT)) {
                        map.put("discount", couponRule.getDiscount());
                    }
                }
            }

            // 预先支付
            BigDecimal preyMoney = BigDecimal.ZERO;
            if (null != order.getAlipayMoney() && order.getAlipayMoney().doubleValue() > 0) {
                preyMoney = order.getAlipayMoney();
            } else if (null != order.getWeixinMoney() && order.getWeixinMoney().doubleValue() > 0) {
                preyMoney = order.getWeixinMoney();
            } else if (null != order.getSignMoney() && order.getSignMoney().doubleValue() > 0) {
                preyMoney = order.getSignMoney();
            } else if (null != order.getBalanceMoney() && order.getBalanceMoney().doubleValue() > 0) {
                preyMoney = order.getBalanceMoney();
            }
            map.put("preyMoney", preyMoney.setScale(2, BigDecimal.ROUND_HALF_UP));

            map.put("employId", driver.getId());
            map.put("employName", driver.getName());
            map.put("employPhone", driver.getPhone());

            map.put("success", true);
            return map;

        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
            return map;
        }

    }

    @RequestMapping(value = "checkTask", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> checkTask(Long orderId) {

        Map<String, Object> map = new HashMap<String, Object>();

        Order order = zhuancheService.findOne(orderId);
        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            map.put("finished", true);
        } else {
            map.put("finished", false);
        }

        map.put("success", true);
        return map;

    }

//  @RequestMapping(value = "confirmTask", method = RequestMethod.POST)
//  public @ResponseBody Map<String, Object> confirmTask(Long orderId, BigDecimal realCash,
//      BigDecimal guoluMoney, BigDecimal yuanchengMoney, BigDecimal otherMoney, Double mileage,
//      Integer waitedTime, Integer travelTime,
//      @RequestParam(required = false, value = "toPlace") String toPlace,
//      @RequestParam(required = false, value = "toPlaceLng") Double toPlaceLng,
//      @RequestParam(required = false, value = "toPlaceLat") Double toPlaceLat,
//      @RequestParam(required = false, value = "startPrice") BigDecimal startPrice,
//      @RequestParam(required = false, value = "mileagePrice") BigDecimal mileagePrice,
//      @RequestParam(required = false, value = "runTimePrice") BigDecimal runTimePrice,
//      @RequestParam(required = false, value = "waitPrice") BigDecimal waitPrice,
//      @RequestParam(required = false, value = "memo") String memo,
//      @RequestParam(required = false, value = "xml") String xml) {
//
//    log.error("recv orderId:{}," + "realCash:{},guoluMoney:{},yuanchengMoney:{},otherMoney:{},"
//        + "mileage:{},waitedTime:{},travelTime:{}," + "toPlace:{},toPlaceLng:{},toPlaceLat:{},"
//        + "startPrice:{},mileagePrice:{},runTimePrice:{},waitPrice:{},memo:{},xml:{}", orderId,
//        realCash, guoluMoney, yuanchengMoney, otherMoney, mileage, waitedTime, travelTime, toPlace,
//        toPlaceLng, toPlaceLat, startPrice, mileagePrice, runTimePrice, waitPrice, memo, xml);
//
//    Map<String, Object> map = new HashMap<String, Object>();
//
//    if (null == orderId || null == realCash || null == mileage || null == waitedTime
//        || null == travelTime) {
//      map.put("success", false);
//      map.put("message", "参数错误");
//      return map;
//    }
//
//    Order order = zhuancheService.findOne(orderId);
//
//    if (null == order) {
//      map.put("success", false);
//      map.put("message", "订单不存在");
//      return map;
//    }
//
//    if (!order.getStatus().equals(Order.ORDER_STATUS_ZHIXING)) {
//      map.put("success", false);
//      map.put("message", "订单状态不正确");
//      return map;
//    }
//
//    if (order.isTreatment()) {
//      map.put("success", true);
//      map.put("type", "waitfinish");
//      return map;
//    }
//
//    try {
//
//      BigDecimal hasPayed = BigDecimal.ZERO;// 之前已经实际支付的钱
//
//      hasPayed = hasPayed.add(order.getSignMoney());
//
//      hasPayed = hasPayed.add(order.getBalanceMoney());
//
//      hasPayed = hasPayed.add(order.getAlipayMoney());
//
//      hasPayed = hasPayed.add(order.getWeixinMoney());
//
//      order.setGuoluMoney(guoluMoney);
//      order.setYuanchengMoney(yuanchengMoney);
//      order.setOtherMoney(otherMoney);
//      order.setRealPay(realCash.doubleValue());
//
//      // 优惠券
//      Coupon coupon = null;
//      BigDecimal coupon_hasPayed = BigDecimal.ZERO;
//      Double discount = null;
//      if (null != order.getCouponId()) {
//        coupon = couponService.findOne(order.getCouponId());
//        if (null != coupon) {
//          if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DEDUCTION)) {
//            coupon_hasPayed = coupon.getCouponRule().getMoney();
//          } else if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
//            discount = coupon.getCouponRule().getDiscount();
//            coupon_hasPayed = (realCash.subtract(order.getGuoluMoney()).multiply(new BigDecimal(
//                1 - (discount / 10)))).setScale(0, BigDecimal.ROUND_DOWN);
//          }
//        }
//      }
//
//      order.setCouponMoney(coupon_hasPayed);
//      if (coupon_hasPayed.doubleValue() > 0 && null == order.getPrePayTypeDetail()) {
//        order.setPrePayTypeDetail(Order.PayTypeDetails.coupon);
//      }
//      order.setDiscount(discount);
//
//      BigDecimal m = new BigDecimal(mileage);
//      double df = m.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
//      order.setMileage(df);
//      order.setMidwayWait(waitedTime);
//      order.setRunTime(travelTime);
//
//      if (null != startPrice) {
//        order.setStartPrice(startPrice.doubleValue());
//      }
//      if (null != mileagePrice) {
//        order.setMileagePrice(mileagePrice.doubleValue());
//      }
//      if (null != runTimePrice) {
//        order.setRunTimePrice(runTimePrice.doubleValue());
//      }
//      if (null != waitPrice) {
//        order.setWaitPrice(waitPrice.doubleValue());
//      }
//
//      if (StringUtils.isNotBlank(toPlace) && null != toPlaceLng && null != toPlaceLat) {
//        if (StringUtils.isBlank(order.getEndAddress())) {
//          order.setEndLng(toPlaceLng);
//          order.setEndLat(toPlaceLat);
//          order.setEndAddress(toPlace);
//        }
//      }
//
//      order.setTreatment(true);
//      order.setMemo(memo);
//      Result<Order> result = zhuancheService.confirmTask(order, xml);
//
//      Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
//      passenger.setPlateNumber(memo);
//      passenger.setMileage(passenger.getMileage() + order.getMileage());// 累计公里数
//      memberService.updatePassenger(passenger);
//
//      if (result.isSuccess()) {
//
//        BigDecimal money = new BigDecimal(order.getRealPay());// 还需支付的钱
//        money = money.subtract(order.getGuoluMoney());
//        money = money.subtract(coupon_hasPayed);
//        if (money.doubleValue() < 0) {
//          money = BigDecimal.ZERO;
//        }
//        money = money.subtract(hasPayed);
//        money = money.add(order.getGuoluMoney());
//
//        if (money.doubleValue() <= 0) {
//          // 直接结算
//          Driver driver = driverService.findOne(order.getEmployId());
//
//          result = zhuancheService.completeTaskNewV3(order, passenger, driver, "clickComplete",
//              null, hasPayed, Boolean.FALSE);
//
//          if (result.isSuccess()) {
//            map.put("success", true);
//            map.put("type", "hasfinished");
//            return map;
//          } else {
//            map.put("success", false);
//            map.put("message", result.getMessage());
//            return map;
//          }
//
//        } else {
//          // 进入确认页面
//
//          // 客户端提醒付费推送
//          ZhuanOrderConfirmEvent zhuanOrderConfirmEvent = new ZhuanOrderConfirmEvent(order);
//          applicationEventMulticaster.multicastEvent(zhuanOrderConfirmEvent);
//
//          map.put("success", true);
//          map.put("type", "waitfinish");
//          return map;
//        }
//      } else {
//        map.put("success", false);
//        map.put("message", result.getMessage());
//        return map;
//      }
//
//    } catch (Exception e) {
//      e.printStackTrace();
//      map.put("success", false);
//      map.put("message", "内部服务器错误");
//      return map;
//    }
//
//  }

    @RequestMapping(value = "finishTask", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> finishTask(Long orderId, String payType, String who) {

        log.error("recv orderId:{},payType{}", orderId, payType);

        Map<String, Object> map = new HashMap<String, Object>();

        if (null == orderId || StringUtils.isBlank(payType)) {
            map.put("success", false);
            map.put("message", "参数错误");
            return map;
        }

        if (!"helppay".equals(payType) && !"sign".equals(payType) && !"balance".equals(payType)) {
            map.put("success", false);
            map.put("message", "支付方式应为代付、签单、余额中的一种");
            return map;
        }

        Order order = zhuancheService.findOne(orderId);

        if (null == order) {
            map.put("success", false);
            map.put("message", "订单不存在");
            return map;
        }

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            map.put("success", false);
            map.put("message", "订单已结算");
            return map;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
            map.put("success", false);
            map.put("message", "订单状态不正确");
            return map;
        }

        if (!order.isTreatment()) {
            map.put("success", false);
            map.put("message", "还未确认订单，不能结算");
            return map;
        }

        Driver driver = driverService.findOne(order.getEmployId());
        if ("helppay".equals(payType)) {// 如果是代付，服务人员收到现金，余额减钱
            if (null == driver) {
                map.put("success", false);
                map.put("message", "订单服务人员不存在，无法代付");
                return map;
            }
        }

        Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
        if (null != passenger) {
            if ("sign".equals(payType)) {// 签单支付
                if (!passenger.isAllowOverdraw()) {
                    map.put("success", false);
                    map.put("message", "当前客户不能签单");
                    return map;
                }
            } else if ("balance".equals(payType)) {// 余额支付

                Double afterPayMoney = 0d;
                if (null != order.getPrePayTypeDetail()) {
                    if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                        afterPayMoney = order.getRealPay() - order.getCouponMoney().doubleValue();
                    } else {
                        afterPayMoney = order.getRealPay() - order.getBudgetPay();
                    }
                } else {
                    afterPayMoney = order.getRealPay();
                }

                if (passenger.getType().equals(Passenger.TYPE_PASSENGER)) {
                    BigDecimal shengyuMoney = BigDecimal.ZERO;
                    shengyuMoney = shengyuMoney.add(passenger.getNodrawMoney());
                    if (passenger.getDrawMoney().doubleValue() > 0) {
                        shengyuMoney = shengyuMoney.add(passenger.getDrawMoney());
                    }
                    if (shengyuMoney.doubleValue() < afterPayMoney) {
                        map.put("success", false);
                        map.put("message", "余额不足");
                        return map;
                    }
                } else if (passenger.getType().equals(Passenger.TYPE_ENTERPRISE)) {
                    Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
                    BigDecimal shengyuMoney = BigDecimal.ZERO;
                    shengyuMoney = shengyuMoney.add(enterprise.getNodrawMoney());
                    if (enterprise.getDrawMoney().doubleValue() > 0) {
                        shengyuMoney = shengyuMoney.add(enterprise.getDrawMoney());
                    }
                    if (shengyuMoney.doubleValue() < afterPayMoney) {
                        map.put("success", false);
                        map.put("message", "余额不足");
                        return map;
                    }
                }

            }
        }

        try {

            Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                "clickPay", payType, null, Boolean.FALSE);

            if (result.isSuccess()) {

                if (StringUtils.isNotBlank(who) && who.equals("passenger")) {
                    OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                        driver, order.getId(), "zhuanche");
                    applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);
                }

                map.put("success", true);
                return map;
            } else {
                map.put("success", false);
                map.put("message", result.getMessage());
                return map;
            }

        } catch (Exception e) {
            e.printStackTrace();
            map.put("success", false);
            map.put("message", "内部服务器错误");
            return map;
        }

    }

    // 查询订单
    @RequestMapping(value = "clientPayData", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> clientPayData(Long orderId) {

        Map<String, Object> map = new HashMap<String, Object>();

        Setting setting = settingUtils.get();

        Order order = zhuancheService.findOne(orderId);

        BigDecimal coupon_hasPayed = order.getCouponMoney();

        // 预支付的金额
        BigDecimal prePayMoney = BigDecimal.valueOf(order.getBudgetPay());
        Coupon coupon = null;
        if (null != order.getCouponId()) {
            coupon = salesApi.findOneCoupon(order.getCouponId()).getResult();
            Double discount = null;
            if (null != coupon) {
                if (coupon.getCouponRule().getType().equals(CouponRule.TYPE_DISCOUNT)) {
                    discount = coupon.getCouponRule().getDiscount();
                }
            }

            if (null != discount) {
                prePayMoney = prePayMoney.subtract(
                    prePayMoney.multiply(
                        BigDecimal.valueOf(1).subtract(BigDecimal.valueOf((discount / 10)))).setScale(0,
                        BigDecimal.ROUND_DOWN)).setScale(2, BigDecimal.ROUND_UP);
            } else {
                prePayMoney = prePayMoney.subtract(coupon_hasPayed);
            }
        }
        map.put("couponMoney", coupon_hasPayed);

        map.put("realCash", new BigDecimal(order.getRealPay()).subtract(order.getGuoluMoney()));
        map.put("guoluMoney", order.getGuoluMoney());
        map.put("yuanchengMoney", order.getYuanchengMoney());
        map.put("otherMoney", order.getOtherMoney());
        map.put("mileage", order.getMileage());
        map.put("runTime", order.getRunTime());
        map.put("mileagePrice", order.getMileagePrice());
        map.put("runTimePrice", order.getRunTimePrice());
        map.put("midwayWait", order.getMidwayWait());
        map.put("waitPrice", order.getWaitPrice());
        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                map.put("preyMoney", BigDecimal.ZERO);
            } else {
                map.put("preyMoney", prePayMoney);
            }
        } else {
            map.put("preyMoney", BigDecimal.ZERO);
        }

        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                BigDecimal payMoney = BigDecimal.valueOf(order.getRealPay());// 还需支付的钱
                payMoney = payMoney.subtract(order.getGuoluMoney());
                payMoney = payMoney.subtract(coupon_hasPayed);
                if (payMoney.doubleValue() < 0) {
                    payMoney = BigDecimal.ZERO;
                }
                payMoney = payMoney.add(order.getGuoluMoney());
                map.put("payMoney", payMoney);
            } else {
                map.put("payMoney", BigDecimal.valueOf(order.getRealPay()).subtract(coupon_hasPayed)
                    .subtract(prePayMoney));
            }
        } else {
            map.put("payMoney", order.getRealPay());
        }

        Boolean aliPay = true;
        Boolean weixinPay = true;

        if (StringUtils.isBlank(setting.getAlipayPartnerID())
            || StringUtils.isBlank(setting.getAlipaySellerID())
            || StringUtils.isBlank(setting.getAlipayPartnerPrivKey())) {
            aliPay = false;
        }
        if (StringUtils.isBlank(setting.getWxAppID()) || StringUtils.isBlank(setting.getWxAppSecret())
            || StringUtils.isBlank(setting.getWxPartnerID())
            || StringUtils.isBlank(setting.getWxPartnerKey())) {
            weixinPay = false;
        }
        Boolean unionPay = true;
        if (StringUtils.isBlank(setting.getMerId()) || StringUtils.isBlank(setting.getAcpProdEnc())
            || StringUtils.isBlank(setting.getAcpProdMiddle())
            || StringUtils.isBlank(setting.getAcpProdRoot())
            || StringUtils.isBlank(setting.getAcpsdkSignCertPath())
            || StringUtils.isBlank(setting.getAcpsdkSignCertPwd())) {
            unionPay = false;
        }
        map.put("unionPay", unionPay);

        map.put("weixinPay", weixinPay);
        map.put("aliPay", aliPay);
        Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
        if (passenger.getType() == Passenger.TYPE_PASSENGER) {
            map.put("overdraw", passenger.isAllowOverdraw());
        } else if (passenger.getType() == Passenger.TYPE_ENTERPRISE) {
            Enterprise enterprise = memberService.findOneEnterprise(passenger.getEnterprise_id());
            map.put("overdraw", enterprise.isAllowOverdraw());
        }

        map.put("success", true);
        return map;
    }

    // 客户端APP后支付
    @RequestMapping(value = "alipay/afterpay")
    public @ResponseBody
    Map<String, Object> alipayAfterpay(HttpServletResponse response,
        HttpServletRequest request, Long orderId) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            Order order = zhuancheService.findOne(orderId);

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode());
                return mapData;
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return mapData;
            }

            if (!order.isTreatment()) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_NOT_CONFIRM.getCode());
                return mapData;
            }

            BigDecimal money = BigDecimal.ZERO;
            if (null != order.getPrePayTypeDetail()) {
                if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                    money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
                } else {
                    money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
                }
            } else {
                money = new BigDecimal(order.getRealPay());
            }
            money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

            PayRecordOrder payRecordOrder = new PayRecordOrder();
            payRecordOrder.setMoney(money);
            payRecordOrder.setOrderId(orderId);
            payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.alipay);
            payRecordOrder.setTreatment(false);
            Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

            Setting setting = settingUtils.get();

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("PartnerID", setting.getAlipayPartnerID());
            map.put("SellerID", setting.getAlipaySellerID());
            map.put("PartnerPrivKey", setting.getAlipayPartnerPrivKey());
            map.put("PartnerPublicKey", AlipayConfig.ali_public_key);
            map.put("tradeNO", "zc_af_" + result.getResult().getId() + "_" + order.getId());
            map.put("productName", "专车结算付费");
            map.put("productDescription", "专车结算付费");
            map.put("amount", money);
            map.put("notifyURL", setting.getWebUrl() + "/api/zhuanche/alipay/afternotify");
            String content = MemberOrderSign.sign(map);
            String sign = RSA.sign(content, setting.getAlipayPartnerPrivKey(), "utf-8");
            sign = URLEncoder.encode(sign, "utf-8");
            String url = content + "&sign=\"" + sign + "\"&sign_type=\"RSA\"";
            mapData.put("success", true);
            mapData.put("url", url);
        } catch (Exception e) {
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // $$$支付宝支付后的接口
    @RequestMapping(value = "alipay/afternotify")
    public synchronized @ResponseBody
    String alipayAfterNotify(HttpServletResponse response,
        HttpServletRequest request) throws UnsupportedEncodingException {
        Setting setting = settingUtils.get();
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<String, String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }

            // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }

        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),
            "UTF-8");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),
            "UTF-8");
        // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        log.error("商户订单号：" + out_trade_no);
        log.error("交易号：" + trade_no + "交易状态：" + trade_status);
        if (AlipayNotify.verify(params, setting)) {// 验证成功
            if (trade_status.equals("TRADE_FINISHED")) {
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = zhuancheService.findOnePayRecordOrder(orderId);
                if (payRecordOrder.isTreatment()) {
                    return "success";
                }

                Order order = zhuancheService.findOne(payRecordOrder.getOrderId());

                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    return "success";
                }

                Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                Driver driver = driverService.findOne(order.getEmployId());

                Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                    "onlinePay", "alipay", null, Boolean.FALSE);

                if (result.isSuccess()) {

                    Result<PayRecordOrder> result2 = zhuancheService.payRecordOrderTreatment(payRecordOrder);

                    if (result2.isSuccess()) {

                        OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                            driver, order.getId(), "zhuanche");
                        applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);

                        return "success";
                    } else {
                        return "fail";
                    }

                } else {
                    return "fail";
                }

            } else if (trade_status.equals("TRADE_SUCCESS")) {
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = zhuancheService.findOnePayRecordOrder(orderId);
                if (payRecordOrder.isTreatment()) {
                    return "success";
                }

                Order order = zhuancheService.findOne(payRecordOrder.getOrderId());

                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    return "success";
                }

                Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                Driver driver = driverService.findOne(order.getEmployId());

                Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                    "onlinePay", "alipay", null, Boolean.FALSE);

                if (result.isSuccess()) {

                    Result<PayRecordOrder> result2 = zhuancheService.payRecordOrderTreatment(payRecordOrder);

                    if (result2.isSuccess()) {

                        OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                            driver, order.getId(), "zhuanche");
                        applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);

                        return "success";
                    } else {
                        return "fail";
                    }

                } else {
                    return "fail";
                }

            }

            return "fail";
        } else {
            return "fail";
        }

    }

    // $$$微信支付前接口
    @RequestMapping(value = "wx/afterpay")
    public synchronized @ResponseBody
    SortedMap<String, String> wxAfterpay(
        HttpServletResponse response, HttpServletRequest request, Long orderId) {

        Order order = zhuancheService.findOne(orderId);

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode()));
            return finalpackage;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_STATUS_ERROR.getCode()));
            return finalpackage;
        }

        if (!order.isTreatment()) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_NOT_CONFIRM.getCode()));
            return finalpackage;
        }

        BigDecimal money = BigDecimal.ZERO;
        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
            } else {
                money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
            }
        } else {
            money = new BigDecimal(order.getRealPay());
        }
        money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

        PayRecordOrder payRecordOrder = new PayRecordOrder();
        payRecordOrder.setMoney(money);
        payRecordOrder.setOrderId(orderId);
        payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.weixin);
        payRecordOrder.setTreatment(false);
        Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

        Setting setting = settingUtils.get();
        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = setting.getWxAppID();
        String appsecret = setting.getWxAppSecret();
        String partner = setting.getWxPartnerID();
        String partnerkey = setting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "专车结算付费-" + order.getOrderNo();
        // 商户订单号
        String out_trade_no = "zc_af_" + result.getResult().getId() + "_" + order.getId();
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100)).intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/zhuanche/wx/afternotify";

        String trade_type = "APP";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
            + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>"
            + trade_type + "</trade_type>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                log.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appid", appid);
        finalpackage.put("partnerid", partner);
        finalpackage.put("prepayid", prepay_id);
        finalpackage.put("package", "Sign=WXPay");
        finalpackage.put("noncestr", nonce_str);
        finalpackage.put("timestamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);

        finalpackage.put("success", Boolean.TRUE.toString());

        return finalpackage;

    }

    // $$$微信支付后接口
    @RequestMapping("wx/afternotify")
    public synchronized @ResponseBody
    String wxAfterNotify(HttpServletResponse response,
        HttpServletRequest request) throws Exception {

        String out_trade_no = "";

        try {

            BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
            String line = null;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            String strxml = sb.toString();

            InputStream in = new ByteArrayInputStream(strxml.getBytes());
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(in);
            Element root = doc.getRootElement();
            List list = root.getChildren();
            Iterator it = list.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String k = e.getName();
                if (k.equals("out_trade_no")) {
                    out_trade_no = e.getText();
                }
            }

            try {
                // 关闭流
                if (null != in) {
                    in.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            if (StringUtils.isBlank(out_trade_no)) {
                return "FAIL";
            }

            Long orderId = Long.valueOf(out_trade_no.split("_")[2]);

            PayRecordOrder payRecordOrder = zhuancheService.findOnePayRecordOrder(orderId);
            if (payRecordOrder.isTreatment()) {
                return "SUCCESS";
            }

            Order order = zhuancheService.findOne(payRecordOrder.getOrderId());

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                return "SUCCESS";
            }

            Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
            Driver driver = driverService.findOne(order.getEmployId());

            Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                "onlinePay", "weixin", null, Boolean.FALSE);

            if (result.isSuccess()) {

                Result<PayRecordOrder> result2 = zhuancheService.payRecordOrderTreatment(payRecordOrder);

                if (result2.isSuccess()) {

                    OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                        driver, order.getId(), "zhuanche");
                    applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);

                    return "SUCCESS";
                } else {
                    return "FAIL";
                }

            } else {
                return "FAIL";
            }

        } catch (Exception e) {
            e.printStackTrace();
            return "FAIL";
        }

    }

    // 微信支付前接口
    @RequestMapping(value = "wx/prepayId_jsapi")
    public synchronized @ResponseBody
    SortedMap<String, String> prepayIdJsapi(
        HttpServletResponse response, HttpServletRequest request, Long orderId, String openid) {

        Order order = zhuancheService.findOne(orderId);

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode()));
            return finalpackage;
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_STATUS_ERROR.getCode()));
            return finalpackage;
        }

        if (!order.isTreatment()) {
            finalpackage.put("success", String.valueOf(false));
            finalpackage.put("message", ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
            finalpackage.put("code", String.valueOf(ErrorConstantV4.ORDER_NOT_CONFIRM.getCode()));
            return finalpackage;
        }

        BigDecimal money = BigDecimal.ZERO;
        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
            } else {
                money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
            }
        } else {
            money = new BigDecimal(order.getRealPay());
        }
        money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

        PayRecordOrder payRecordOrder = new PayRecordOrder();
        payRecordOrder.setMoney(money);
        payRecordOrder.setOrderId(orderId);
        payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.weixin);
        payRecordOrder.setTreatment(false);
        Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

        Setting setting = settingUtils.get();
        WxSetting wxSetting = settingUtils.getWx();

        String createOrderURL = Configuration.createOrderURL;

        // 商户相关资料
        String appid = wxSetting.getWxAppId();
        String appsecret = wxSetting.getWxAppSecret();
        String partner = wxSetting.getWxPartnerId();
        String partnerkey = wxSetting.getWxPartnerKey();

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "专车订单-" + order.getOrderNo();
        // 商户订单号
        String out_trade_no = "zc_js_" + result.getResult().getId() + "_" + order.getId();
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100)).intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = setting.getWebUrl() + "/api/zhuanche/wx/afternotify";

        String trade_type = "JSAPI";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", openid);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
            + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>"
            + trade_type + "</trade_type>" + "<openid>" + openid + "</openid>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                log.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appId", appid);
        finalpackage.put("timeStamp", timestamp);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", "prepay_id=" + prepay_id + "");
        finalpackage.put("signType", "MD5");
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("paySign", finalsign);

        return finalpackage;

    }

    // 微信支付前接口
    @RequestMapping(value = "wx/miniProgramPay")
    public synchronized @ResponseBody
    ResultTransport miniProgramPay(HttpServletResponse response,
        HttpServletRequest request, Long orderId, String jsCode) {

        Order order = zhuancheService.findOne(orderId);

        if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.ORDER_HAS_BEEN_FINISHED);
        }

        if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
            return ResultTransport.getErrorBy(ErrorConstantV4.ORDER_STATUS_ERROR);
        }

        if (!order.isTreatment()) {
            return ResultTransport.getErrorBy(ErrorConstantV4.ORDER_NOT_CONFIRM);
        }

        WxSetting wxSetting = settingUtils.getWx();
        Setting sysSetting = settingUtils.get();

        // 商户相关资料
        String appid = wxSetting.getWxAppIdMP();
        String appsecret = wxSetting.getWxAppSecretMP();
        String partner = wxSetting.getWxPartnerIdMP();
        String partnerkey = wxSetting.getWxPartnerKeyMP();

        // 验证是否得到了APPID/APPSECRET/jsCode
        if (null == appid || appid.isEmpty()) {
            return ResultTransport.getErrorBy(ErrorConstantV4.APPID_NOT_SET);
        }
        if (null == appsecret || appsecret.isEmpty()) {
            return ResultTransport.getErrorBy(ErrorConstantV4.APPSECRET_NOT_SET);
        }
        if (null == jsCode || jsCode.isEmpty()) {
            return ResultTransport.getErrorBy(ErrorConstantV4.JSCODE_IS_EMPTY);
        }

        // 获取该用户的openid
        String openid = WeixinUtil.getOpenid(appid, appsecret, jsCode);
        if (openid == null) {
            return ResultTransport.getErrorBy(ErrorConstantV4.GET_USER_OPENID_ERROR);
        }

        BigDecimal money = BigDecimal.ZERO;
        if (null != order.getPrePayTypeDetail()) {
            if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
            } else {
                money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
            }
        } else {
            money = new BigDecimal(order.getRealPay());
        }
        money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

        PayRecordOrder payRecordOrder = new PayRecordOrder();
        payRecordOrder.setMoney(money);
        payRecordOrder.setOrderId(orderId);
        payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.weixin);
        payRecordOrder.setTreatment(false);
        Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

        String createOrderURL = Configuration.createOrderURL;

        // 获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
        String currTime = TenpayUtil.getCurrTime();
        // 8位日期
        String strTime = currTime.substring(8, currTime.length());
        // 四位随机数
        String strRandom = TenpayUtil.buildRandom(6) + "";
        // 10位序列号,可以自行调整。
        String strReq = strTime + strRandom;
        // 商户号
        String mch_id = partner;
        // 随机数
        String nonce_str = strReq;
        // 商品描述
        String body = "专车结算付费-" + order.getOrderNo();
        // 商户订单号
        String out_trade_no = "zc_af_" + result.getResult().getId() + "_" + order.getId();
        // 总金额以分为单位，不带小数点
        String total_fee = String.valueOf(money.multiply(new BigDecimal(100)).intValue());
        // 订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr();

        // 这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        String notify_url = sysSetting.getWebUrl() + "/api/zhuanche/wx/afternotify";

        String trade_type = "JSAPI";

        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid", appid);
        packageParams.put("mch_id", mch_id);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);

        // 这里写的金额为1 分到时修改
        // packageParams.put("total_fee", "1");
        packageParams.put("total_fee", total_fee);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url", notify_url);
        packageParams.put("trade_type", trade_type);
        packageParams.put("openid", openid);

        RequestHandler reqHandler = new RequestHandler(request, response);
        reqHandler.init(appid, appsecret, partnerkey);

        String sign = reqHandler.createSign(packageParams);
        String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>"
            + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"
            + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>"
            + out_trade_no
            + "</out_trade_no>"
            +
            // "<total_fee>"+1+"</total_fee>"+
            "<total_fee>" + total_fee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip
            + "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>"
            + trade_type + "</trade_type>" + "<openid>" + openid + "</openid>" + "</xml>";

        String prepay_id = "";
        try {
            prepay_id = new GetWxOrderno().getPayNo(createOrderURL, xml);
            if (prepay_id.equals("")) {
                log.error("统一支付接口获取预支付订单出错");
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        }

        SortedMap<String, String> finalpackage = new TreeMap<String, String>();
        String timestamp = Sha1Util.getTimeStamp();
        finalpackage.put("appId", appid);
        finalpackage.put("nonceStr", nonce_str);
        finalpackage.put("package", "prepay_id=" + prepay_id);
        finalpackage.put("signType", "MD5");
        finalpackage.put("timeStamp", timestamp);
        String finalsign = reqHandler.createSign(finalpackage);
        finalpackage.put("sign", finalsign);

        ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
        instance.setData(finalpackage);
        return instance;
    }

    // 翼支付支付前接口
    @RequestMapping(value = "bestpay/afterpay")
    public @ResponseBody
    Map<String, Object> bestpayAfterpay(HttpServletResponse response,
        HttpServletRequest request, Long orderId) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            Order order = zhuancheService.findOne(orderId);

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode());
                return mapData;
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return mapData;
            }

            if (!order.isTreatment()) {
                mapData.put("success", false);
                mapData.put("message", ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_NOT_CONFIRM.getCode());
                return mapData;
            }

            BigDecimal money = BigDecimal.ZERO;
            if (null != order.getPrePayTypeDetail()) {
                if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                    money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
                } else {
                    money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
                }
            } else {
                money = new BigDecimal(order.getRealPay());
            }
            money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

            PayRecordOrder payRecordOrder = new PayRecordOrder();
            payRecordOrder.setMoney(money);
            payRecordOrder.setOrderId(orderId);
            payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.alipay);
            payRecordOrder.setTreatment(false);
            Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

            // 获取系统设置
            Setting setting = settingUtils.get();
            String callBackUrl = setting.getWebUrl() + "/api/zhuanche/bestpay/afternotify";
            String createUrl = "https://webpaywg.bestpay.com.cn/order.action";

            // 获取商户信息
            String mch_id = setting.getMerchantId();
            String mch_key = setting.getMerKey();
            String mch_pwd = setting.getMchPwd();
            String riskInfo = setting.getRiskcontrolinfo();
            String attach_order_id = "zc_af_" + result.getResult().getId() + "_" + order.getId(); // 商户订单号,这里作为附加信息，因为订单不能个包含特殊字符
            String body = "专车结算付费-" + order.getOrderNo();

            // 使用随机数来作为订单流水号
            String currTime = TenpayUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length()); // 8位日期
            String strRandom = TenpayUtil.buildRandom(6) + ""; // 四位随机数
            String strReq = strTime + strRandom; // 10位序列号,可以自行调整

            String phone = order.getPassengerPhone();
            // 格式化金额0.00
            DecimalFormat myformat = new java.text.DecimalFormat("0.00");
            String money_ = myformat.format(money);

            // 订单模型
            String total_fee = String.valueOf(money.multiply(new BigDecimal(100)).intValue()); // 元转分
            BestPayOrderModel orderModel = new BestPayOrderModel();
            orderModel.setATTACH(attach_order_id);
            orderModel.setCITYCODE("");
            orderModel.setDIVDETAILS("");
            orderModel.setENCODE("");
            orderModel.setENCODETYPE("1");
            orderModel.setKEY(mch_key);
            orderModel.setLOGINNO("");
            orderModel.setMERCHANTID(mch_id);
            orderModel.setORDERAMT(total_fee); // 分
            orderModel.setORDERCCY("RMB");
            orderModel.setORDERREQTIME(currTime);
            orderModel.setORDERREQTRANSEQ(strReq);
            orderModel.setORDERSEQ(strReq);
            orderModel.setPRODUCTDESC(body);
            orderModel.setPRODUCTID("04");
            orderModel.setPROVINCECODE("");
            orderModel.setRISKCONTROLINFO(riskInfo);
            orderModel.setSERVICECODE("05");
            orderModel.setSESSIONKEY("");
            orderModel.setSUBMERCHANTID("");
            orderModel.setTRANSCODE("01");
            boolean rs = BestPayCreateOrder.createByApp(createUrl, orderModel);

            // 下单失败
            if (!rs) {
                mapData.put("success", false);
                mapData.put("message", "翼支付app下单失败");
                return mapData;
            }

            // 签名参数
            StringBuffer md5Buffer = new StringBuffer();
            md5Buffer.append("SERVICE=").append("mobile.security.pay").append("&MERCHANTID=")
                .append(mch_id).append("&MERCHANTPWD=").append(mch_pwd).append("&SUBMERCHANTID=")
                .append("").append("&BACKMERCHANTURL=").append(callBackUrl).append("&ORDERSEQ=")
                .append(strReq).append("&ORDERREQTRANSEQ=").append(strReq).append("&ORDERTIME=")
                .append(currTime).append("&ORDERVALIDITYTIME=").append("").append("&CURTYPE=")
                .append("RMB").append("&ORDERAMOUNT=").append(money_).append("&SUBJECT=").append(body)
                .append("&PRODUCTID=").append("04").append("&PRODUCTDESC=").append(body)
                .append("&CUSTOMERID=").append(phone).append("&SWTICHACC=").append("true")
                .append("&KEY=").append(mch_key);

            // 签名
            log.info("MAC(MD5)--before--String：" + md5Buffer.toString());
            String sign = CryptTool.md5Digest(md5Buffer.toString());
            log.info("MAC(MD5)--after--String:" + sign);

            // 拼接返回数据串
            StringBuffer paramsBuffer = new StringBuffer();
            paramsBuffer
                .append("SERVICE=")
                .append("mobile.security.pay")
                .append("&MERCHANTID=")
                .append(mch_id)
                // 签约商户号
                .append("&MERCHANTPWD=").append(mch_pwd).append("&SUBMERCHANTID=").append("")
                .append("&BACKMERCHANTURL=").append(callBackUrl).append("&SIGNTYPE=").append("MD5")
                .append("&SIGN=").append(sign).append("&ORDERSEQ=").append(strReq)
                .append("&ORDERREQTRANSEQ=").append(strReq).append("&ORDERTIME=").append(currTime)
                .append("&ORDERVALIDITYTIME=").append("").append("&ORDERAMOUNT=").append(money_)
                .append("&CURTYPE=").append("RMB").append("&PRODUCTID=").append("04")
                .append("&PRODUCTDESC=").append(body).append("&PRODUCTAMOUNT=").append(money_)
                .append("&ATTACHAMOUNT=").append("0.00").append("&ATTACH=").append(attach_order_id)
                .append("&DIVDETAILS=").append("").append("&ACCOUNTID=").append("")
                .append("&CUSTOMERID=").append(phone).append("&USERIP=").append("").append("&BUSITYPE=")
                .append("04").append("&SWTICHACC=").append("true").append("&SUBJECT=").append(body);

            // 返回数据
            String params = paramsBuffer.toString();

            mapData.put("success", true);
            mapData.put("params", params);
        } catch (Exception e) {
            mapData.put("success", false);
            mapData.put("message", "支付接口请求失败");
        }
        return mapData;
    }

    // 翼支付支付后的接口
    @RequestMapping(value = "bestpay/afternotify")
    public synchronized @ResponseBody
    String bestpayAfterNotify(HttpServletResponse response,
        HttpServletRequest request) throws UnsupportedEncodingException {

        try {
            // 准备
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();

            // 获取回调数据，注释部分为没有使用的部分数据，其所代表的意义详见翼支付APP文档
            String UPTRANSEQ = request.getParameter("UPTRANSEQ");
            String MERCHANTID = request.getParameter("MERCHANTID");
            String TRANDATE = request.getParameter("TRANDATE");
            String RETNCODE = request.getParameter("RETNCODE");
            String RETNINFO = request.getParameter("RETNINFO");
            // String ORDERREQTRANSEQ = request.getParameter("ORDERREQTRANSEQ");
            String ORDERSEQ = request.getParameter("ORDERSEQ");
            String ORDERAMOUNT = request.getParameter("ORDERAMOUNT");
            // String PRODUCTAMOUNT = request.getParameter("PRODUCTAMOUNT");
            // String ATTACHAMOUNT = request.getParameter("ATTACHAMOUNT");
            // String CURTYPE = request.getParameter("CURTYPE");
            // String ENCODETYPE = request.getParameter("ENCODETYPE");
            // String BANKID = request.getParameter("BANKID");
            String ATTACH = request.getParameter("ATTACH");
            // String UPREQTRANSEQ = request.getParameter("UPREQTRANSEQ");
            // String UPBANKTRANSEQ = request.getParameter("UPBANKTRANSEQ");
            // String PRODUCTNO = request.getParameter("PRODUCTNO");
            String SIGN = request.getParameter("SIGN");

            // 验证签名
            Setting setting = settingUtils.get();
            String key = setting.getMerKey();
            String signStr = "UPTRANSEQ=" + UPTRANSEQ + "&MERCHANTID=" + MERCHANTID + "&ORDERSEQ="
                + ORDERSEQ + "&ORDERAMOUNT=" + ORDERAMOUNT + "&RETNCODE=" + RETNCODE + "&RETNINFO="
                + RETNINFO + "&TRANDATE=" + TRANDATE + "&KEY=" + key;
            String localSign = CryptTool.md5Digest(signStr);

            // 验签失败
            if (!localSign.equals(SIGN)) {
                out.write("UPTRANSEQ_" + UPTRANSEQ);
                log.info("支付回调，验签失败！");
                return "fail";
            }

            // 验签成功，看是否支付成功("0000为成功，其他均为失败")
            if (RETNCODE.equals("0000")) {
                Long orderId = Long.valueOf(ATTACH.split("_")[2]);
                PayRecordOrder payRecordOrder = zhuancheService.findOnePayRecordOrder(orderId);
                if (payRecordOrder.isTreatment()) {
                    return "success";
                }

                Order order = zhuancheService.findOne(payRecordOrder.getOrderId());

                if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                    return "success";
                }

                Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                Driver driver = driverService.findOne(order.getEmployId());

                Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                    "onlinePay", "bestpay", null, Boolean.FALSE);

                if (result.isSuccess()) {

                    Result<PayRecordOrder> result2 = zhuancheService.payRecordOrderTreatment(payRecordOrder);

                    if (result2.isSuccess()) {

                        OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                            driver, order.getId(), "zhuanche");
                        applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);

                        return "success";
                    } else {
                        return "fail";
                    }
                } else {
                    return "fail";
                }
            }
            return "fail";
        } catch (Exception e) {
            // 异常不返回，以便不丢失支付数据
            e.printStackTrace();
            return "fail";
        }

    }

    /**
     * 专车新单推送
     *
     * @param orderId
     * @return
     */
    @RequestMapping(value = "pushNewOrder")
    public @ResponseBody
    Map<String, Object> pushNewOrder(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            ZhuanOrderCreateEvent createEvent = new ZhuanOrderCreateEvent(order.getId(), null);
            applicationEventMulticaster.multicastEvent(createEvent);

            ZhuanOrderRecordEvent orderRecordEvent = new ZhuanOrderRecordEvent(order.getId());
            applicationEventMulticaster.multicastEvent(orderRecordEvent);
        } catch (Exception e) {
            log.error("pushNewOrder error : " + e.getMessage());
        }
        return map;
    }

    /**
     * @param orderId
     * @return
     */
    @RequestMapping(value = "acceptOrder")
    public @ResponseBody
    Map<String, Object> acceptOrder(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            if (null != order) {
                Driver driver = driverService.findOne(order.getEmployId());
                if (null != driver) {

                    if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                        driverService.updateStatusAndJobStatus(Driver.DRIVER_BUSY,
                            Driver.DRIVER_JOBSTATUS_ZHUANCHE, driver.getId());
                    }

                    ZhuanOrderAcceptEvent acceptEvent = new ZhuanOrderAcceptEvent(order, driver);
                    applicationEventMulticaster.multicastEvent(acceptEvent);
                }
            }
        } catch (Exception e) {
            log.error("acceptOrder error : " + e.getMessage());
        }
        return map;
    }

    /**
     * @param orderId
     * @return
     */
    @RequestMapping(value = "cancelOrder")
    public @ResponseBody
    Map<String, Object> cancelOrder(Long orderId, Long employId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            Driver driver = driverService.findOne(employId);
            ZhuanOrderCancelEvent cancelEvent = new ZhuanOrderCancelEvent(order, driver, "customerCancel");
            applicationEventMulticaster.multicastEvent(cancelEvent);
        } catch (Exception e) {
            log.error("acceptOrder error : " + e.getMessage());
        }
        return map;
    }

    @RequestMapping(value = "pushWaitZhuan")
    public @ResponseBody
    Map<String, Object> pushWaitZhuan(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            Company orderCompany = companyService.findOne(order.getCompanyId());
            Company finalCompany = orderCompany;
            Company main = companyService.getMain();
            Setting setting = settingUtils.get();
            if (!main.getId().equals(orderCompany.getId()) && setting.isSmsMainCompany()) {
                finalCompany = main;
            }
            SmsTemplet templet = smsService.findByAlias(finalCompany.getId(),
                SmsType.driverAccept);
            if (templet != null && StringUtils.isNotBlank(templet.getContent())) {
                Driver driver = driverService.findOne(order.getEmployId());
//        smsService.sendSms(order.getPassengerPhone(), "arriveFromZhuanchePlace", "{\"服务人员名\":\""
//            + order.getEmployName() + "\",\"服务人员工号\":\"" + driver.getUsername()
//            + "\",\"服务人员电话\":\"" + order.getEmployPhone() + "\",\"订单号\":\"" + order.getOrderNo()
//            + "\",\"预约地\":\"" + order.getStartAddress() + "\"}", finalCompany.getId(), 0,
//            finalCompany.getSignName());
                com.alibaba.fastjson.JSONObject smsParam = new com.alibaba.fastjson.JSONObject();
                smsParam.put("name", order.getEmployName());
                smsParam.put("user", driver.getUsername());
                smsParam.put("tel", order.getEmployPhone());
                smsParam.put("order", order.getOrderNo());
                smsService.sendSms(order.getPassengerPhone(), templet.getTemplateId(), smsParam.toJSONString(), finalCompany.getId(), 0, finalCompany.getSignName());
            }
        } catch (Exception e) {
            log.error("pushWaitZhuan error : " + e.getMessage());
        }
        return map;
    }

    @RequestMapping(value = "pushRunOrder")
    public @ResponseBody
    Map<String, Object> pushRunOrder(Long orderId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            Passenger passenger = memberService.findOnePassenger(order.getPassengerId());

            ZhuanOrderRunEvent zhuanOrderRunEvent = new ZhuanOrderRunEvent(order, passenger);
            applicationEventMulticaster.multicastEvent(zhuanOrderRunEvent);
        } catch (Exception e) {
            log.error("pushRunOrder error : " + e.getMessage());
        }
        return map;
    }

    @RequestMapping(value = "arriveOrder")
    public @ResponseBody
    Map<String, Object> arriveOrder(Long orderId, Long passengerId) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            Passenger passenger = memberService.findOnePassenger(passengerId);
            ZhaunOrderArriveEvent zhuanOrderArriveEvent = new ZhaunOrderArriveEvent(order, passenger);
            applicationEventMulticaster.multicastEvent(zhuanOrderArriveEvent);
        } catch (Exception e) {
            log.error("acceptOrder error : " + e.getMessage());
        }
        return map;
    }

    @RequestMapping(value = "refuseOrder")
    public @ResponseBody
    Map<String, Object> refuseOrder(Long orderId, Long employId, String memo) {
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Order order = zhuancheService.findOne(orderId);
            Driver driver = driverService.findOne(employId);

            if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                driverService.updateStatusAndJobStatus(Driver.DRIVER_ONLINE, null, driver.getId());
            }

            // 拒绝工单记录
            DriverRefuseRecord driverRefuseRecord = new DriverRefuseRecord();
            driverRefuseRecord.setEmployId(driver.getId());
            driverRefuseRecord.setEmployRealName(driver.getRealname());
            driverRefuseRecord.setEmployUserName(driver.getUsername());
            driverRefuseRecord.setEmployPhone(driver.getPhone());
            driverRefuseRecord.setHappend(new Date());
            driverRefuseRecord.setOrderId(order.getId());
            driverRefuseRecord.setOrderNumber(order.getOrderNo());
            driverRefuseRecord.setOrderCompanyId(order.getCompanyId());
            driverRefuseRecord.setMemo(memo);
            driverRefuseRecord.setOrderType(DriverRefuseRecord.OrderType.zhuanche);
            driverRefuseRecordService.save(driverRefuseRecord);
        } catch (Exception e) {
            log.error("acceptOrder error : " + e.getMessage());
        }
        return map;
    }

    /**
     * 客户端APP后支付(银联支付)
     */
    @RequestMapping(value = "unionpay/afterpay")
    public @ResponseBody
    Map<String, Object> unionpayAfterpay(HttpServletResponse response,
        HttpServletRequest request, Long orderId) {
        Map<String, Object> mapData = new HashMap<String, Object>();
        try {

            Order order = zhuancheService.findOne(orderId);

            if (order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                mapData.put("message", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_HAS_BEEN_FINISHED.getCode());
                return mapData;
            }

            if (!order.getStatus().equals(Order.ORDER_STATUS_ARRIVE_DISTANCE)) {
                mapData.put("message", ErrorConstantV4.ORDER_STATUS_ERROR.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_STATUS_ERROR.getCode());
                return mapData;
            }

            if (!order.isTreatment()) {
                mapData.put("message", ErrorConstantV4.ORDER_NOT_CONFIRM.getMessage());
                mapData.put("code", ErrorConstantV4.ORDER_NOT_CONFIRM.getCode());
                return mapData;
            }

            BigDecimal money = BigDecimal.ZERO;
            if (null != order.getPrePayTypeDetail()) {
                if (order.getPrePayTypeDetail().equals(PayTypeDetails.coupon)) {
                    money = new BigDecimal(order.getRealPay()).subtract(order.getCouponMoney());
                } else {
                    money = new BigDecimal(order.getRealPay() - order.getBudgetPay());
                }
            } else {
                money = new BigDecimal(order.getRealPay());
            }
            money = money.setScale(2, BigDecimal.ROUND_HALF_UP);

            PayRecordOrder payRecordOrder = new PayRecordOrder();
            payRecordOrder.setMoney(money);
            payRecordOrder.setOrderId(orderId);
            payRecordOrder.setPayRecordTypeOrder(PayRecordTypeOrder.unionpay);
            payRecordOrder.setTreatment(false);
            Result<PayRecordOrder> result = zhuancheService.createPayRecordOrder(payRecordOrder);

            Setting setting = settingUtils.get();

            // 从classpath加载acp_sdk.properties文件
            SDKConfig.getConfig().loadPropertiesFromSrc(setting);

            String payOrderId = DemoBase.getOrderId();
            int paymoney = money.multiply(new BigDecimal(100)).intValue(); // txnAmt以'元'为单位,乘以100以'分'为单位传给银联
            String txnTime = DemoBase.getCurrentTime(); // 交易时间
            String merId = setting.getMerId(); // 获取商户号
            Map<String, String> contentData = new HashMap<String, String>();

            /*** 银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改 ***/
            contentData.put("version", "5.1.0"); // 版本号 全渠道默认值
            contentData.put("encoding", "UTF-8"); // 字符集编码 可以使用UTF-8,GBK两种方式
            contentData.put("signMethod", "01"); // 签名方法
            contentData.put("txnType", "01"); // 交易类型 01:消费
            contentData.put("txnSubType", "01"); // 交易子类 01：消费
            contentData.put("bizType", "000201"); // 填写000201
            contentData.put("channelType", "08"); // 渠道类型 08手机

            /*** 商户接入参数 ***/
            contentData.put("merId", merId); // 商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
            contentData.put("accessType", "0"); // 接入类型，商户接入填0 ，不需修改（0：直连商户， 1： 收单机构
            // 2：平台商户）
            contentData.put("orderId", payOrderId); // 商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则
            contentData.put("txnTime", txnTime); // 订单发送时间，取系统时间，格式为YYYYMMDDhhmmss，必须取当前时间，否则会报txnTime无效
            contentData.put("accType", "01"); // 账号类型 01：银行卡02：存折03：IC卡帐号类型(卡介质)
            contentData.put("txnAmt", String.valueOf(paymoney)); // 交易金额 单位为分，不能带小数点
            contentData.put("currencyCode", "156"); // 境内商户固定 156 人民币
            String out_trade_no = "zc_af_" + result.getResult().getId() + "_" + order.getId();
            contentData.put("reqReserved", out_trade_no);
            String backUrl = "";
            if (setting.getWebUrl().endsWith("/")) {
                backUrl = setting.getWebUrl() + "api/zhuanche/unionpay/afternotify";
            } else {
                backUrl = setting.getWebUrl() + "/" + "api/zhuanche/unionpay/afternotify";
            }
            contentData.put("backUrl", backUrl);

            Map<String, String> reqData = AcpService.sign(contentData, DemoBase.encoding); // 报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
            String requestAppUrl = SDKConfig.getConfig().getAppRequestUrl(); // 交易请求url从配置文件读取对应属性文件acp_sdk.properties中的
            // acpsdk.backTransUrl
            Map<String, String> rspData = AcpService
                .post(reqData, requestAppUrl, DemoBase.encoding); // 发送请求报文并接受同步应答（默认连接超时时间30秒，读取返回结果超时时间30秒）;这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过

            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    LogUtil.writeLog("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        String tn = rspData.get("tn");
                        mapData.put("message", "成功");
                        mapData.put("code", 0);
                        mapData.put("data", tn);
                        return mapData;
                    } else {
                        mapData.put("message", "验证签名失败");
                        mapData.put("code", -1);
                        return mapData;
                    }
                } else {
                    mapData.put("message", "验证签名失败");
                    mapData.put("code", -1);
                    return mapData;
                }
            } else {
                mapData.put("message", "验证签名失败");
                mapData.put("code", -1);
                return mapData;
            }

        } catch (Exception e) {
            mapData.put("message", "支付接口请求失败");
            mapData.put("code", -4);
        }
        return mapData;
    }

    /**
     * 银联支付后的接口
     *
     * @throws IOException
     */
    @RequestMapping(value = "unionpay/afternotify")
    public synchronized @ResponseBody
    void unionpayAfterNotify(HttpServletResponse resp,
        HttpServletRequest req) throws IOException {
        LogUtil.writeLog("BackRcvResponse接收后台通知开始");

        String encoding = req.getParameter(SDKConstants.param_encoding);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParam(req);

        LogUtil.printRequestLog(reqParam);

        Map<String, String> valideData = null;
        if (null != reqParam && !reqParam.isEmpty()) {
            Iterator<Entry<String, String>> it = reqParam.entrySet().iterator();
            valideData = new HashMap<String, String>(reqParam.size());
            while (it.hasNext()) {
                Entry<String, String> e = it.next();
                String key = (String) e.getKey();
                String value = (String) e.getValue();
                valideData.put(key, value);
            }
        }

        // 重要！验证签名前不要修改reqParam中的键值对的内容，否则会验签不过
        if (!AcpService.validate(valideData, encoding)) {
            LogUtil.writeLog("验证签名结果[失败].");
            // 验签失败，需解决验签问题
        } else {
            LogUtil.writeLog("验证签名结果[成功].");
            LogUtil.writeLog("后台通知的数据orderId:" + valideData.get("orderId"));
            String respCode = valideData.get("respCode");
            if ("00".equals(respCode)) {
                String out_trade_no = valideData.get("reqReserved"); // 获取后台通知的数据，其他字段也可用类似方式获取
                // 验证成功
                Long orderId = Long.valueOf(out_trade_no.split("_")[2]);
                PayRecordOrder payRecordOrder = zhuancheService.findOnePayRecordOrder(orderId);
                if (!payRecordOrder.isTreatment()) {
                    Order order = zhuancheService.findOne(payRecordOrder.getOrderId());
                    if (!order.getStatus().equals(Order.ORDER_STATUS_OK)) {
                        Passenger passenger = memberService.findOnePassenger(order.getPassengerId());
                        Driver driver = driverService.findOne(order.getEmployId());

                        Result<Order> result = zhuancheService.completeTaskNewV3(order, passenger, driver,
                            "onlinePay", "unionpay", null, Boolean.FALSE);

                        if (result.isSuccess()) {

                            Result<PayRecordOrder> result2 = zhuancheService
                                .payRecordOrderTreatment(payRecordOrder);

                            if (result2.isSuccess()) {

                                OrderPassengerHasPayEvent orderPassengerHasPayEvent = new OrderPassengerHasPayEvent(
                                    driver, order.getId(), "zhuanche");
                                applicationEventMulticaster.multicastEvent(orderPassengerHasPayEvent);

                                // 返回给银联服务器http 200 状态码
                                resp.getWriter().print("ok");
                            }
                        }
                    }
                }
            }
        }
        LogUtil.writeLog("BackRcvResponse接收后台通知结束");

    }

    /**
     * 获取请求参数中所有的信息.
     *
     * @param request
     * @return
     */
    public static Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                // 在报文上送时，如果字段的值为空，则不上送<下面的处理为在获取所有参数数据时，判断若值为空，则删除这个字段>
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }
}
